home *** CD-ROM | disk | FTP | other *** search
- /*
- General purpose ST pic file reader source code.
- Reads Neo, DEGAS, DEGAS compressed, & Tiny formats.
- This code is public domain. Written by John Brochu.
- Set tabs to 4 for best results.
-
- To use, you must set up a screen buffer (32000 bytes)
- (or use the current system screen address to read the pic
- directly into screen memory), palette buffer (16 ints),
- and a resolution flag (1 int).
-
- The pic is read into a temporary buffer, unpacked if needed,
- and moved to the proper buffers. You may then display the pic
- by using the appropriate bios calls to set the resolution/palette/
- screen address. If you use a pic buffer rather than screen memory,
- be sure the buffer is on a 256-byte boundary!
-
- My source to compress a pic to DEGAS compressed format is also included.
- */
-
- /* Globals */
- char tmp_buf[32000], /* Temp buffer where file is read in */
- *iff_in, *iff_out; /* Pointers for DEGAS unpack() routine */
-
- /*---------------------------------------------------------------------------*/
- /* |--------- DEGAS ---------| */
- /* UNCOMPRESSED COMPRESSED */
- /* NEO low med mono low med mono TINY */
- /* typ... 0 1 2 3 4 5 6 7 */
- /* Returns length of file or (neg) error code. */
-
- long load_pic(fil_nam, pic_adr, pic_pal, pic_rez, typ)
- char *fil_nam; /* Pointer to filename */
- long pic_adr; /* Addr of pic buffer */
- int *pic_pal; /* Pointer to palette buffer */
- int *pic_rez; /* Pointer to res variable */
- int typ; /* Pic type (see above) */
- {
- char buf[130], /* Temp storage for file header */
- *p;
- int x,
- hndl, /* File handle */
- retry_flg, /* Allows a retry on file error (not used) */
- pal_ofs, /* Offset into file to palette */
- ctl_ofs, /* Offset to control segment (Tiny) */
- dat_ofs, /* Offset to data segment (Tiny) */
- ctrl_len, /* Length of control segment (Tiny) */
- data_len, /* Length of data segment (Tiny) */
- lines; /* #lines in pic */
- long length, /* Length of file read in */
- hdr_len, /* Length of file header (non-data) */
- ctl_in, /* Addr of Tiny control segment */
- dat_in; /* Addr of Tiny data segment */
-
- do {
- retry_flg = 0;
- graf_mouse(HOURGLASS, 0L);
- length = Fopen(fil_nam, 0);
- if (length < 0) /* File not found */
- continue;
- hndl = length; /* Otherwise file handle was returned */
- if (typ==0) { /* NeoChrome (0) */
- hdr_len = 128L;
- pal_ofs = 4;
- } else if (typ < 7) { /* DEGAS (1-6) */
- hdr_len = 34L;
- pal_ofs = 2;
- } else { /* Tiny (7) */
- hdr_len = 37L; /* (assume no color rotation info for now) */
- pal_ofs = 1;
- ctl_ofs = 33;
- dat_ofs = 35;
- }
- length = Fread(hndl, hdr_len, buf); /* Read header */
- if (length < 0) /* Error, abort (critical error) */
- retry_flg = 0;
- else { /* All's well, process the file... */
- if (typ==7) /* Check pic res... */
- x = buf[0] & 7; /* Mask Tiny rotation flag */
- else {
- p = &x; /* Get res in x */
- *p++ = buf[pal_ofs-2];
- *p++ = buf[pal_ofs-1];
- }
- if (((typ>0)&&(typ<7)) && (x & 0x8000)) { /* DEGAS compr. flag */
- typ = (x & 3) + 4;
- x &= 0x7fff;
- }
- if ((typ==7) && (x > 2)) { /* Tiny rotation flag */
- length = Fread(hndl, 4L, &buf[hdr_len]); /* Read the xtra */
- if (length < 0) { /* Error, abort (critical error) */
- retry_flg = 0;
- continue;
- }
- x -= 3; /* Mask off the rotation flag */
- pal_ofs += 4; /* Adjust offsets... */
- ctl_ofs += 4;
- dat_ofs += 4;
- }
- if ((x < 0)||(x > 2)) { /* Invalid res flag, */
- Fclose(hndl); /* assume bad pic file */
- graf_mouse(ARROW, 0L);
- return(-1L);
- }
- *pic_rez = x;
- for (x=0; x<32; ++x)
- *(pic_pal+x) = buf[x+pal_ofs]; /* Get palette */
- if (typ < 4) { /* Read DEGAS, Neo uncompressed screen image... */
- length = Fread(hndl, 32000L, pic_adr);
- if (length < 0)
- retry_flg = 0; /* Abort (read error) */
- } else if (typ < 7) { /* Read and uncompress DEGAS screen... */
- length = Fread(hndl, 32000L, tmp_buf);
- if (length < 0)
- retry_flg = 0; /* Abort (read error) */
- else {
- x = *pic_rez;
- if (x < 2) lines = 200; /* Low, med-res */
- else lines = 400; /* Monochrome */
- iff_in = tmp_buf;
- iff_out = pic_adr;
- do unpack(x); /* Unpack a line at a time */
- while (--lines);
- }
- } else { /* Tiny format */
- /* Note: since Tiny pics always have an odd # of header bytes,
- we read starting at an odd addr to speed things up. */
- length = Fread(hndl, 32000L, tmp_buf+1);
- if (length < 0)
- retry_flg = 0; /* Abort (read error) */
- else {
- p = &ctrl_len; /* Get control length...*/
- *p++ = buf[ctl_ofs];
- *p++ = buf[ctl_ofs+1];
- p = &data_len; /* Get data length... */
- *p++ = buf[dat_ofs];
- *p++ = buf[dat_ofs+1];
- ctl_in = tmp_buf + 1; /* Addr of control segment, */
- dat_in = tmp_buf + 1 + ctrl_len; /* data segment */
- untiny(ctl_in, dat_in, pic_adr, ctrl_len);
- }
- }
- }
- Fclose(hndl);
- } while (retry_flg);
- graf_mouse(ARROW, 0L);
- return(length);
- }
-
- /*---------------------------------------------------------------------------*/
-
- /* Unpacks a single scan line & updates iff_in & iff_out global pointers
-
- / byt == 0 to 127 copy next [byt+1] bytes
- Unpack routine --if-< byt == -1 to -127 copy next byte [-byt+1] times
- \ byt == 128 NO-OP */
-
- unpack(rez)
- int rez;
- {
- register char *src_ptr, *dst_ptr, byt, cnt;
- register int minus128 = -128, len;
- char linbuf[320]; /* Oversize just in case! */
- int llen;
-
-
- if (rez < 2) len = 160;
- else len = 80;
- llen = len;
- src_ptr = iff_in;
- dst_ptr = &linbuf[0];
-
- while (len > 0) {
- byt = *src_ptr++;
- if (byt >= 0) {
- ++byt;
- do {
- *dst_ptr++ = *src_ptr++;
- --len;
- } while (--byt);
- }
- else if (byt != minus128) {
- cnt = -byt + 1;
- byt = *src_ptr++;
- do {
- *dst_ptr++ = byt;
- --len;
- } while (--cnt);
- }
- }
- ilbm_st(linbuf, iff_out, rez);
- iff_in = src_ptr; /* Update global pointers */
- iff_out += llen;
- }
-
- /*---------------------------------------------------------------------------*/
-
- ilbm_st(src_ptr, dst_ptr, rez) /* Convert ILBM format line to ST format */
- int *src_ptr, *dst_ptr, rez;
- {
- int x, *p0_ptr, *p1_ptr, *p2_ptr, *p3_ptr;
-
- if (rez==0) { /* Low-res */
- p0_ptr = src_ptr;
- p1_ptr = src_ptr + 20;
- p2_ptr = src_ptr + 40;
- p3_ptr = src_ptr + 60;
- for (x=0; x<20; ++x) {
- *dst_ptr++ = *p0_ptr++;
- *dst_ptr++ = *p1_ptr++;
- *dst_ptr++ = *p2_ptr++;
- *dst_ptr++ = *p3_ptr++;
- }
- } else if (rez==1) { /* Med-res */
- p0_ptr = src_ptr;
- p1_ptr = src_ptr + 40;
- for (x=0; x<40; ++x) {
- *dst_ptr++ = *p0_ptr++;
- *dst_ptr++ = *p1_ptr++;
- }
- } else { /* Monochrome */
- for (x=0; x<40; ++x)
- *dst_ptr++ = *src_ptr++;
- }
- }
-
- /*---------------------------------------------------------------------------
- Unpacks a single scan line & updates iff_in & iff_out global pointers
-
- / byt == 0 to 127 copy next [byt+1] bytes
- Unpack routine --if-< byt == -1 to -127 copy next byte [-byt+1] times
- \ byt == 128 NO-OP
- */
-
- unpack(rez)
- int rez;
- {
- register char *src_ptr, *dst_ptr, byt, cnt;
- register int minus128 = -128, len;
- char linbuf[200];
- int llen;
-
-
- if (rez < 2) len = 160;
- else len = 80;
- llen = len;
- src_ptr = iff_in;
- dst_ptr = &linbuf[0];
-
- while (len > 0) {
- byt = *src_ptr++;
- if (byt >= 0) {
- ++byt;
- do {
- *dst_ptr++ = *src_ptr++;
- --len;
- } while (--byt);
- }
- else if (byt != minus128) {
- cnt = -byt + 1;
- byt = *src_ptr++;
- do {
- *dst_ptr++ = byt;
- --len;
- } while (--cnt);
- }
- }
- ilbm_st(linbuf, iff_out, rez);
- iff_in = src_ptr; /* Update global pointers */
- iff_out += llen;
- }
-
- /*---------------------------------------------------------------------------*/
-
- ilbm_st(src_ptr, dst_ptr, rez) /* Convert ILBM format line to ST format */
- int *src_ptr, *dst_ptr, rez; /* (ILBM = InterLeaved BitMap) */
- {
- int x, *p0_ptr, *p1_ptr, *p2_ptr, *p3_ptr;
-
- if (rez==0) { /* Low-res */
- p0_ptr = src_ptr;
- p1_ptr = src_ptr + 20;
- p2_ptr = src_ptr + 40;
- p3_ptr = src_ptr + 60;
- for (x=0; x<20; ++x) {
- *dst_ptr++ = *p0_ptr++;
- *dst_ptr++ = *p1_ptr++;
- *dst_ptr++ = *p2_ptr++;
- *dst_ptr++ = *p3_ptr++;
- }
- } else if (rez==1) { /* Med-res */
- p0_ptr = src_ptr;
- p1_ptr = src_ptr + 40;
- for (x=0; x<40; ++x) {
- *dst_ptr++ = *p0_ptr++;
- *dst_ptr++ = *p1_ptr++;
- }
- } else { /* Monochrome */
- for (x=0; x<40; ++x)
- *dst_ptr++ = *src_ptr++;
- }
- }
-
- /*---------------------------------------------------------------------------*/
-
- /* Packs a single scan line & updates iff_in & iff_out global pointers */
- /* Returns # of bytes written to output buffer */
-
- long pack()
- {
- register char *src_ptr, *dst_ptr, *run_ptr,
- c, lastc, repcnt, runcnt, runlen;
- char linbuf[200];
- int len, plen, pln;
- long iff0_out = iff_out;
-
- if (pic_rez == 0) {
- len = 160;
- pln = 4;
- } else if (pic_rez == 1) {
- len = 160;
- pln = 2;
- } else {
- len = 80;
- pln = 1;
- }
- plen = len/pln; /* Scan length (1 plane) in bytes */
- st_ilbm(iff_in, linbuf, pic_rez); /* Unweave the planes into ILBM form */
- iff_in += len; /* Update global pointer */
- src_ptr = &linbuf[0];
- dst_ptr = iff_out;
-
- for (; pln; --pln) { /* Pack each scan line's plane separately */
- len = plen - 1;
- run_ptr = src_ptr;
- lastc = *src_ptr++;
- repcnt = runcnt = 1;
-
- for (; len; --len) {
- c = *src_ptr++; /* Get next input byte */
- ++runcnt; /* Increment run counter */
- if (c == lastc) ++repcnt; /* Increment repeat counter */
- else {
- if (repcnt > 2) { /* If >2 chars repeated, output the run */
- runlen = runcnt - repcnt - 1;
- if (runlen) { /* Output copy-run if pending... */
- *dst_ptr++ = runlen - 1;
- for (; runlen; --runlen)
- *dst_ptr++ = *run_ptr++;
- }
- *dst_ptr++ = (char)1 - repcnt; /* Output repeat-run... */
- *dst_ptr++ = lastc;
- runcnt = 1; /* Reset run counter */
- run_ptr = src_ptr - 1; /* & copy-run pointer */
- }
- repcnt = 1;
- lastc = c;
- }
- }
-
- if (repcnt > 2) { /* End of scan line, finish up... */
- runlen = runcnt - repcnt;
- if (runlen) { /* Output copy-run if one is pending... */
- *dst_ptr++ = runlen - 1;
- for (; runlen; --runlen)
- *dst_ptr++ = *run_ptr++;
- }
- *dst_ptr++ = (char)1 - repcnt; /* Output repeat-run... */
- *dst_ptr++ = lastc;
- } else {
- *dst_ptr++ = runcnt - 1; /* Output copy-run... */
- for (; runcnt; --runcnt)
- *dst_ptr++ = *run_ptr++;
- }
- }
-
- iff_out = dst_ptr;
- return(iff_out - iff0_out);
- }
-
- /*---------------------------------------------------------------------------*/
-
- st_ilbm(src_ptr, dst_ptr, rez) /* Convert ST scan line to ILBM format */
- int *src_ptr, *dst_ptr, rez;
- {
- int x, *p0_ptr, *p1_ptr, *p2_ptr, *p3_ptr;
-
- if (rez==0) { /* Low-res */
- p0_ptr = dst_ptr;
- p1_ptr = dst_ptr + 20;
- p2_ptr = dst_ptr + 40;
- p3_ptr = dst_ptr + 60;
- for (x=0; x<20; ++x) {
- *p0_ptr++ = *src_ptr++;
- *p1_ptr++ = *src_ptr++;
- *p2_ptr++ = *src_ptr++;
- *p3_ptr++ = *src_ptr++;
- }
- } else if (rez==1) { /* Med-res */
- p0_ptr = dst_ptr;
- p1_ptr = dst_ptr + 40;
- for (x=0; x<40; ++x) {
- *p0_ptr++ = *src_ptr++;
- *p1_ptr++ = *src_ptr++;
- }
- } else { /* Monochrome */
- for (x=0; x<40; ++x)
- *dst_ptr++ = *src_ptr++;
- }
- }
-